#!/usr/bin/env python
# encoding: utf-8

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from common.widgets.TableView import TableView
from ui.flowDialog import Ui_Dialog

import os
import math
import numpy as np
import binascii
import configparser

import pyqtgraph as pg
from pyqtgraph import GraphicsLayoutWidget
from pyqtgraph import GraphicsWindow

from common.libs.Excel import Excel
from common.libs.MathFunc import MathFunc
from common.libs.ComDeal import ComDeal
from common.libs.ComDeal import WATER_CMD


import pysnooper
import logging
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')


# filename = '%s/log/%s_debug.log'%(os.getcwd(), time.strftime("%Y%m%d", time.localtime()))

class FlowDataDeal():

    def __init__(self):
        pass

    def linearInterpolation(self, y1,y2,x1,x2,x):
        """ 斜率差值法 """
        k = (y2-y1)/(x2-x1)
        b = y1-k*x1
        y = k*x + b
        return y

    def check_table(self, pluse):
        """ 流量计算查表法 """
        factor = [0.52687, 0.53022, 0.53419, 0.54467]
        flow_speed = [500, 1000, 1500, 2000]
        pluse_speed = [s/f for f, s in zip(factor, flow_speed)]

        val = 0.53
        for i in range(0, len(factor)):
            if pluse <= pluse_speed[0]:
                val = self.linearInterpolation(factor[0], factor[1], pluse_speed[0], pluse_speed[1], pluse)
                break
            if pluse >= pluse_speed[-1]:
                val = self.linearInterpolation(factor[-2], factor[-1], pluse_speed[-2], pluse_speed[-1], pluse)
                break
            if i > 0:
                if pluse_speed[i-1] < pluse < pluse_speed[i]:
                    val = self.linearInterpolation(factor[i-1], factor[i], pluse_speed[i-1], pluse_speed[i], pluse)
                    break
        return val

    def find_stable_start(self, x=None, press=None, direction="", threshold=0):
        """找到曲线稳定的开始位置"""
        num = 10 # 步数
        step = 5 # 步长
        for i in range(len(x)):
            if i < len(x) - num*step:
                err = []
                find = True
                for j in range(num):
                    err.append(abs(press[i+step*(j+1)] - press[i+step*j]))
                    # 差值超出阈值
                    if err[j] > threshold:
                        find = False
                if find:
                    if direction == "+":
                        if press[i+step] > 0:
                            return x[i+step]
                    if direction == "-":
                        if press[i+step] < 0:
                            return x[i+step]
        return None
    
    def getFlowSpeed(self, x, y):
        """ 斜率查表计算流量 """
        # 累积流量
        flow_sum = 0
        t_sum = 0
        step =  20
        step_len = int(len(x)/step)
        for i in range(step_len):
            if i > 0:
                t = ((x[i*step] - x[(i-1)*step]) / 1000 /60)
                pluse = (y[i*step] - y[(i-1)*step])
                if t > 0:
                    speed = pluse/t
                    # 根据系数查表
                    factor = self.check_table(speed)
                    flow = factor*pluse 
                    flow_sum += flow
                    t_sum += t
        # 多余部分
        other_step = len(x)%step
        if  other_step > 0:
            print("多余部分:%s-%s"%(x[-1] , x[-other_step]))
            t = ((x[-1] - x[-other_step]) / 1000 /60)
            pluse = (y[-1] - y[-other_step])
            if t > 0:
                speed = pluse/t
                # 根据系数查表
                factor = self.check_table(speed)
                flow = factor*pluse 
                flow_sum += flow
                t_sum += t

        if abs(t_sum) > 0:
            flow_speed = flow_sum/t_sum
            # return t_sum, flow_sum, flow_speed
            return t_sum*1000*60, flow_sum/1000, flow_speed/1000
        return 0, 0, 0
        # print("累积流量:%s" % flow_sum)
        # print("平均流速:%s" % (flow_sum/t_sum))

    def getStableArea(self, x, flow, press, direction):
        # 正向稳定区域
        if direction == '+':
            start_pos = self.find_stable_start(x=x, press=press, direction=direction, threshold=0.05)
            if start_pos:
                end_pos = x[press.index(max(press))]
                return start_pos, end_pos
        if direction == '-':
            start_pos = self.find_stable_start(x=x, press=press, direction=direction, threshold=0.3)
            if start_pos:
                end_pos = x[press.index(min(press))]
                return start_pos, end_pos
            
    def findStableStart_err(self, x=None, press=None):
        """差值查找稳定开始位置, 适合查找正向压力稳定区域起始位置 """
        num = 10 # 步数
        step = 5 # 步长
        threshold=0.05 # 差值阈值
        for i in range(len(x)):
            if i < len(x) - num*step:
                err = []
                find = True
                for j in range(num):
                    err.append(abs(press[i+step*(j+1)] - press[i+step*j]))
                    # 差值超出阈值
                    if err[j] > threshold:
                        find = False
                if find:
                    if press[i+step] > 0:
                        return x[i+step]
        return 0

    def findStableStart_k(self, x, flow):
        """ k线角度查找算法, 适合查找反向流量稳定区域起始位置 """
        length = len(x)
        num = 10 
        step = 10
        k_angle = 5 # 斜率角度阈值
        for i in range(length):
            if i < length - num*step:
                k_list = []
                for j in range(num):
                    # 时间转换为分钟
                    t = (x[i+step*(j+1)] - x[i+step*j]) / 1000 / 60
                    y = (flow[i+step*(j+1)] - flow[i+step*j]) 
                    k = abs(y / t)
                    k_list.append(math.atan(k) * 180 / 3.14)
                err = False
                for k in k_list:
                    if k <  k_angle:
                        err = True
                if not err:
                    return x[i+step]
        return 0

class graphWidget(GraphicsLayoutWidget):
    def __init__(self):
        super(graphWidget, self).__init__()

        self.ci.border = (100,100,100)

        text = """Data Selection From Image.<br>\n """

        w1 = self.addLayout(row=0, col=0)
        label1 = w1.addLabel(text, row=0, col=0)
        self.plot_flow = pg.PlotItem()
        self.plot_flow = w1.addPlot(row=1, col=0)

        text = """User-Modifiable ROIs<br> """
        w2 = self.addLayout(row=0, col=1)
        label2 = w2.addLabel(text, row=0, col=0)
        v2a = w2.addViewBox(row=1, col=0, lockAspect=True)
        r2a = pg.PolyLineROI([[0,0], [10,10], [10,30], [30,10]], closed=True)
        v2a.addItem(r2a)
        r2b = pg.PolyLineROI([[0,-20], [10,-10], [10,-30]], closed=False)
        v2a.addItem(r2b)
        v2a.disableAutoRange('xy')
        #v2b.disableAutoRange('xy')
        v2a.autoRange()
        #v2b.autoRange()


class LineGraphWidget(GraphicsLayoutWidget):

    cnt = 0

    # 流量和压力范围
    flow_min = -2000
    flow_max = 2000

    # 流量开始阈值
    flow_start_threshold = 0
    flow_max_threshold = 500

    # 压力范围
    press_min = -5
    press_max = 5

    # 边扫描边计算
    # 扫描位置
    scan_start_pos = 0
    scan_end_pos = 0

    positive_average_flow = 0
    positive_sum_flow = 0
    positive_sum_t = 0

    reverse_average_flow = 0
    reverse_sum_flow = 0
    reverse_sum_t = 0

    positive_max_press = 0
    reverse_max_press = 0

    def __init__(self):
        super(LineGraphWidget, self).__init__()
        # 设置边框
        # self.ci.border = (100,100,100)
        self.pg = pg
        # 曲线处理
        self.deal = FlowDataDeal()
        # 流量曲线初始
        self.flow_line_init()
        # 压力曲线初始
        self.press_line_init()

        self.drawRegionFlow(0, 1)
        self.drawRegionPress(0, 1)

    def flow_line_init(self):
        """ 流量曲线 """
        # 流量曲线
        self.flow_w = self.addLayout(row=0, col=0)
        self.plot_flow = self.flow_w.addPlot(row=1, col=0)
        # 坐标显示
        self.label_flow = pg.TextItem("[0,1]", anchor=(0.5, -1.0))
        self.plot_flow.addItem(self.label_flow)
        self.label_flow.setPos(0, 1)
        # 点位显示
        self.scatter_pos_flow = pg.ScatterPlotItem(
            size=10, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 255, 120))
        self.scatter_pos_flow.setData([0, 0], [0, 1])
        self.plot_flow.addItem(self.scatter_pos_flow)
        # 曲线
        self.curve_x_flow = [0,1000]
        self.curve_y_flow = [self.flow_min,self.flow_max]
        self.curve_flow = self.plot_flow.plot(self.curve_x_flow, self.curve_y_flow, name='流量',
                                              pen=self.pg.mkPen('r', width=2))
        # 曲线设置
        self.plot_flow.setYRange(self.flow_min, self.flow_max)
        self.plot_flow.setAutoVisible(y=True)
        self.plot_flow.setLabel('left', "流量(ml)", units='')
        self.plot_flow.setLabel('bottom', "时间(ms)", units='')
        self.plot_flow.showGrid(x=True, y=True, alpha=0.7)
        # 文本显示
        html = """
            <div style="text-align: center">
                <span style="color: #FFF;">类型|时间(ms)|累积(ml)|平均(L/min)|</span><br>
                <span style="color: #FFF;">吸液|%.0f|%.1f|%.1f</span><br>
                <span style="color: #FFF;">冲液|%.0f|%.1f|%.1f</span>
            </div>
            """ % (0,0,0,0,0,0)
        self.text_flow = pg.TextItem(html=html,anchor=(-0.3,0.5), angle=0, border='w', fill=(0, 0, 255, 100))
        self.text_flow.setPos(0, self.flow_max)
        # self.plot_flow.addItem(self.text_flow)

        # 文本显示
        html = """
            <div style="text-align: center">
                <span style="color: #FFF;font-size:10px;">时间(ms):%.0f</span><br>
                <span style="color: #FFF;font-size:10px;">累积(ml):%.3f</span><br>
                <span style="color: #FFF;font-size:10px;">平均(L/min):%.3f</span>
            </div>
            """ % (0,0,0)
        self.text_flow_time = pg.TextItem(html=html,anchor=(-0.3,0.5), angle=0, border='w', fill=(0, 0, 255, 100))
        self.text_flow_time.setPos(0, self.flow_max/2)
        self.plot_flow.addItem(self.text_flow_time)

        self.plot_flow.autoRange()
        # 鼠标移动绑定
        self.vb_flow = self.plot_flow.vb
        self.proxy_flow = self.pg.SignalProxy(
            self.plot_flow.scene().sigMouseMoved, rateLimit=60, slot=self.mouseMoved)

    def press_line_init(self):
        """ 压力曲线 """
        self.w_press= self.addLayout(row=0, col=1)
        self.plot_press = self.w_press.addPlot(row=1, col=0)
        # 坐标显示
        self.label_press = pg.TextItem("[0,1]", anchor=(0.5, -1.0))
        self.plot_press.addItem(self.label_press)
        # 点位
        self.scatter_pos_press = pg.ScatterPlotItem(
            size=10, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 255, 120))
        self.scatter_pos_press.setData([0, 0], [0, 1])
        self.plot_press.addItem(self.scatter_pos_press)
        # 文本显示
        html = """
            <div style="text-align: center">
                <span style="color: #FFF;">[吸液]最大:%.1f kPa </span><br>
                <span style="color: #FFF;">[冲液]最大:%.1f kPa </span>
            </div>
        """ % (0,0)
        self.text_press = pg.TextItem(html=html,anchor=(-0.3,0.5), angle=0, border='w', fill=(0, 0, 255, 100))
        self.text_press.setPos(0, self.press_max)
        self.plot_press.addItem(self.text_press)

        self.curve_x_press = [0, 1000]
        self.curve_y_press = [self.press_min, self.press_max]
        self.curve_press = self.plot_press.plot(self.curve_x_press, self.curve_y_press, name='压力',
                                                pen=self.pg.mkPen('g', width=2))
        # 曲线设置
        self.plot_press.setYRange(self.press_min, self.press_max)
        self.plot_press.setAutoVisible(y=True)
        self.plot_press.setLabel('left', "压力(kPa)", units='')
        self.plot_press.setLabel('bottom', "时间(ms)", units='')
        self.plot_press.showGrid(x=True, y=True, alpha=0.7)
        self.plot_press.autoRange()
        # 鼠标移动绑定
        self.vb_press = self.plot_press.vb
        self.proxy_press = self.pg.SignalProxy(
            self.plot_press.scene().sigMouseMoved, rateLimit=60, slot=self.mouseMoved)

    def find_nearest(self, array, value):
        try:
            idx = (np.abs(array - value)).argmin()
            return idx
        except Exception as e:
            return -1

    def mouseMoved(self, evt):
        pos = evt[0]
        if self.plot_flow.sceneBoundingRect().contains(pos):
            mousePoint = self.vb_flow.mapSceneToView(pos)
            x = mousePoint.x()
            y = mousePoint.y()
            # self.vLine_flow.setPos(mousePoint.x())
            # self.hLine_flow.setPos(mousePoint.y())
            # self.setCursor(Qt.BlankCursor)

            idx = self.find_nearest(np.array(self.curve_x_flow), x)
            if idx >= 0:
                pos_x = self.curve_x_flow[idx]
                pos_y = self.curve_y_flow[idx]
                self.scatter_pos_flow.setData([pos_x], [pos_y])
                self.label_flow.setText("[%s,%s]" % (pos_x, pos_y))
                self.label_flow.setPos(pos_x, pos_y)
        if self.plot_press.sceneBoundingRect().contains(pos):
            mousePoint = self.vb_press.mapSceneToView(pos)
            x = mousePoint.x()
            y = mousePoint.y()
            # self.vLine_press.setPos(mousePoint.x())
            # self.hLine_press.setPos(mousePoint.y())
            # self.setCursor(Qt.BlankCursor)

            idx = self.find_nearest(np.array(self.curve_x_press), x)
            if idx >= 0:
                pos_x = self.curve_x_press[idx]
                pos_y = self.curve_y_press[idx]
                self.scatter_pos_press.setData([pos_x], [pos_y])
                self.label_press.setText("[%s,%s]" % (pos_x, pos_y))
                self.label_press.setPos(pos_x, pos_y)

    def drawLine(self, x, y):
        self.curve_master.setData(x=self.curve_data_x, y=self.curve_flow_data)
        self.curve_slave.setData(x=self.curve_data_x, y=self.curve_press_data)

    def draw_two(self, x, flow, press):
        self.curve_x_flow.append(x)
        self.curve_y_flow.append(flow)
        self.curve_flow.setData(x=self.curve_x_flow, y=self.curve_y_flow)

        self.curve_x_press.append(x)
        self.curve_y_press.append(press)
        self.curve_press.setData(x=self.curve_x_press, y=self.curve_y_press)

        # 实时数据处理
        if self.cnt > 0:
            self.dealTimeV1(self.curve_x_flow, self.curve_y_flow, self.curve_y_press)
        self.cnt += 1

        self.plot_flow.autoRange()
        self.plot_press.autoRange()

    def drawLineFlow(self, pos, pen='b'):
        line = self.plot_flow.plot(
            [self.curve_x_flow[pos], self.curve_x_flow[pos]], [self.flow_min / 2, self.flow_max / 2], pen=self.pg.mkPen(pen, width=1))

    def drawLinePress(self, pos, pen='b'):
        line = self.plot_press.plot(
            [self.curve_x_press[pos], self.curve_x_press[pos]], [self.press_min / 2, self.press_max / 2], pen=self.pg.mkPen(pen, width=1))

    def drawRegionFlow(self, start, end):
        self.region_flow = self.pg.LinearRegionItem([self.curve_x_flow[start],self.curve_x_flow[end]])
        self.region_flow.setZValue(-10)
        self.plot_flow.addItem(self.region_flow)
        self.region_flow.sigRegionChanged.connect(self.sigRegionChangedFlow)

    def drawRegionPress(self, start, end):
        self.region_press = self.pg.LinearRegionItem([self.curve_x_press[start],self.curve_x_press[end]])
        self.region_press.setZValue(-10)
        self.plot_press.addItem(self.region_press)
        self.region_press.sigRegionChanged.connect(self.sigRegionChangedFlow)

    # @pysnooper.snoop()
    def sigRegionChangedFlow(self):
        region = self.region_flow.getRegion()
        try:
            start = region[0]
            end = region[1]
            start_idx = self.find_nearest(np.array(self.curve_x_press), start)
            end_idx = self.find_nearest(np.array(self.curve_x_press), end)
            t_sum, flow_sum, flow_speed = self.deal.getFlowSpeed(x=self.curve_x_flow[start_idx:end_idx], y=self.curve_y_flow[start_idx:end_idx])
            html = """
                <div style="text-align: center">
                    <span style="color: #FFF;font-size:10px;">时间(ms):%.0f</span><br>
                    <span style="color: #FFF;font-size:10px;">累积(L):%.3f</span><br>
                    <span style="color: #FFF;font-size:10px;">平均(L/min):%.3f</span>
                </div>
                """ % (t_sum,flow_sum,flow_speed)
            self.text_flow_time.setHtml(html)
        except:
            pass

    def dealTimeV1(self, x, flow, press):
        """实时处理"""
        length = len(x)
        i = self.cnt
        if i < length:
            if abs(flow[i-1]) == self.flow_start_threshold and abs(flow[i]) != self.flow_start_threshold:
                self.scan_start_pos = i
            if abs(flow[i] - flow[i-1]) > self.flow_max_threshold:
                self.scan_end_pos = i-1
                if self.scan_end_pos > self.scan_start_pos:
                    start_pos = self.scan_start_pos
                    end_pos = self.scan_end_pos
                    # 画出区域
                    print("找到区域时间: %s - %s" % (x[start_pos], x[end_pos]))
                    # self.drawLineFlow(start_pos)
                    # self.drawLineFlow(end_pos)
                    # self.drawLinePress(start_pos)
                    # self.drawLinePress(end_pos)
                    # 找出区域内稳定位置
                    stable_start = 0
                    stable_end = 0
                    direction = '-'
                    if flow[start_pos + 100] > 0: # 正向
                        direction = '+'
                        stable_start = self.deal.findStableStart_err(x[start_pos:end_pos], press[start_pos:end_pos])
                        # stable_start, stable_end = self.deal.getStableArea(x[start_pos:end_pos], flow[start_pos:end_pos], press[start_pos:end_pos], direction='+')
                    if flow[start_pos + 100] < 0: # 反向 采用k值查找稳定区域
                        direction = '-'
                        stable_start = self.deal.findStableStart_k(x[start_pos:end_pos], flow[start_pos:end_pos])
                        # stable_start, stable_end = self.deal.getStableArea_K(x[start_pos:end_pos], flow[start_pos:end_pos], press[start_pos:end_pos], direction='-')
                    if stable_start > 0 :
                        start_idx = x.index(stable_start)
                        # end_idx = x.index(stable_end)
                        end_idx = end_pos-1
                        # if direction == '-':
                        #     start_idx += 60
                        print("找到稳定位置时间: (%s-%s)" % (x[start_idx], x[end_idx]))
                        self.drawLineFlow(start_idx, pen='b')
                        self.drawLineFlow(end_idx, pen='b')
                        self.drawLinePress(start_idx, pen='b')
                        self.drawLinePress(end_idx, pen='b')
                        # self.drawRegionFlow(start_idx, end_idx)

                        t_sum, flow_sum, flow_speed = self.deal.getFlowSpeed(x=x[start_idx:end_idx], y=flow[start_idx:end_idx])

                        text = pg.TextItem("%.0fms \r\n%.3f L\r\n%.3f L/min"%(t_sum, flow_sum, flow_speed))
                        # if direction == '+':
                        #     text.setPos(x[start_idx], self.flow_max/2)
                        # if direction == "-":
                        text.setPos(x[start_idx], self.flow_min/3)
                        self.plot_flow.addItem(text)
                        # html = """
                        #         <div style="text-align: center">
                        #             <span style="color: #FFF;">类型|时间(ms)|累积(ml)|平均(L/min)|</span><br>
                        #             <span style="color: #FFF;">吸液|%.0f|%.2f|%.2f</span><br>
                        #             <span style="color: #FFF;">冲液|%.0f|%.2f|%.2f</span>
                        #         </div>
                        #     """ % (self.positive_sum_t, self.positive_sum_flow,self.positive_average_flow,
                        #             self.reverse_sum_t,self.reverse_sum_flow, self.reverse_average_flow)
                        # self.text_flow.setHtml(html)

                # start = x.index(start_pos)
                # end = x.index(end_pos)
                # res = self.getFlowSpeed(x=x[start:end], y=flow[start:end])




    def dealTime(self, x, flow, press):
        """实时处理"""
        length = len(x)
        i = self.cnt
        if i < length:
            if abs(flow[i-1]) == self.flow_start_threshold and abs(flow[i]) != self.flow_start_threshold:
                self.scan_start_pos = i - 1
                print("找到起始位置: %s" % self.scan_start_pos)
                # 画出当前起始线
                line_start_flow = self.plot_flow.plot(
                    [x[self.scan_start_pos], x[self.scan_start_pos]], [self.flow_min / 2, self.flow_max / 2], pen=self.pg.mkPen('b', width=1))
                line_start_press = self.plot_press.plot(
                    [x[self.scan_start_pos], x[self.scan_start_pos]], [self.press_min / 2, self.press_max / 2], pen=self.pg.mkPen('b', width=1))
            if abs(flow[i] - flow[i-1]) > self.flow_max_threshold:
                self.scan_end_pos = i-1
                print("找到结束位置: %s" % self.scan_end_pos)
                if self.scan_end_pos > self.scan_start_pos: 
                    # 画出当前结束线
                    line_end_flow = self.plot_flow.plot(
                        [x[self.scan_end_pos], x[self.scan_end_pos]], [self.flow_min / 2, self.flow_max / 2], pen=self.pg.mkPen('b', width=1))
                    line_end_press = self.plot_press.plot(
                        [x[self.scan_end_pos], x[self.scan_end_pos]], [self.press_min / 2, self.press_max / 2], pen=self.pg.mkPen('b', width=1))
                    return

                    # 流量计算
                    p_max = self.scan_end_pos
                    p_min = self.scan_start_pos
                    # 时间间隔
                    t = abs(x[p_max] - x[p_min])
                    # 累积流量
                    flow_sum = flow[p_max] - flow[p_min]
                    if flow_sum > 0 : # 吸液
                        direction = "吸液"
                        self.positive_sum_t += t
                        self.positive_sum_flow += abs(flow_sum)
                        self.positive_average_flow = self.positive_sum_flow / self.positive_sum_t
                    if flow_sum < 0 : # 冲液
                        direction = "冲液"
                        self.reverse_sum_t += t
                        self.reverse_sum_flow += abs(flow_sum)
                        self.reverse_average_flow = self.reverse_sum_flow / self.reverse_sum_t
                    flow_sum = abs(flow_sum)
                    # 平均流量
                    flow_average = flow_sum / t
                    # 流量显示文字
                    text = pg.TextItem("%s\r\n%.0f ms\r\n%.2f ml\r\n%.2f L/min"%(direction, t, flow_sum, flow_average))
                    if direction == "吸液":
                        text.setPos(x[p_min], flow[p_max] * 2)
                    if direction == "冲液":
                        text.setPos(x[p_min], flow[p_max] * 1)
                    self.plot_flow.addItem(text)

                    html = """
                            <div style="text-align: center">
                                <span style="color: #FFF;">类型|时间(ms)|累积(ml)|平均(L/min)|</span><br>
                                <span style="color: #FFF;">吸液|%.0f|%.2f|%.2f</span><br>
                                <span style="color: #FFF;">冲液|%.0f|%.2f|%.2f</span>
                            </div>
                        """ % (self.positive_sum_t, self.positive_sum_flow,self.positive_average_flow,
                                self.reverse_sum_t,self.reverse_sum_flow, self.reverse_average_flow)
                    self.text_flow.setHtml(html)
                    # 压力计算
                    press_max = max([abs(p) for p in press[p_min:p_max]])
                    text = pg.TextItem("%s\r\n%.0f ms\r\n%.1fkPa"%(direction, t, press_max))
                    if direction == "吸液":
                        self.positive_max_press = max([self.positive_max_press, press_max])
                        text.setPos(x[p_min], press_max * 2)
                    if direction == "冲液":
                        self.reverse_max_press = max([self.reverse_max_press, press_max])
                        text.setPos(x[p_min], -press_max * 1)
                    self.plot_press.addItem(text)
                    html = """
                        <div style="text-align: center">
                            <span style="color: #FFF;">[吸液]最大压力:%.2f kPa </span><br>
                            <span style="color: #FFF;">[冲液]最大压力:%.2f kPa </span>
                        </div>
                    """ % (self.positive_max_press, self.reverse_max_press)
                    self.text_press.setHtml(html)


    def clear_data(self):
        self.curve_x_flow = []
        self.curve_y_flow = []

        self.curve_x_press = []
        self.curve_y_press = []

        self.curve_flow.setData(x=[], y=[])
        self.curve_press.setData(x=[], y=[])

        self.plot_press.setYRange(self.press_min, self.press_max)
        self.plot_flow.setYRange(self.flow_min, self.flow_max)

    
    def getResult(self, data):
        x = []
        flow = []
        press = []
        length = len(data)
        for i in range(length):
            x.append(float(data[i][0]))
            flow.append(float(data[i][1]))
            press.append(float(data[i][2]))
        pos = []
        for i in range(length):
            if abs(flow[i]) == self.flow_start_threshold and abs(flow[i+1]) != self.flow_start_threshold:
                start_pos = i
                pos.append(start_pos)
            if abs(flow[i] - flow[i-1]) > self.flow_max_threshold:
                end_pos = i - 1
                pos.append(end_pos)
        pos = sorted(pos)

        # 第一个为最大值时，剔除
        if abs(flow[pos[0]]) > self.flow_max_threshold:
            del pos[0]
        # 最后一个不是最大值时，剔除
        if abs(flow[pos[-1]]) < self.flow_max_threshold:
            del pos[-1]

        info = []
        for i in range(int(len(pos) / 2)):
            info.append(pos[i*2:(i+1)*2])

        flow_all_sum = 0
        flow_all_t = 0
        for item in info:
            p_min = item[0]
            p_max = item[1]
            # 时间间隔
            t = abs(x[p_max] - x[p_min])
            flow_all_t += t
            # 累积流量
            flow_sum = flow[p_max] - flow[p_min]
            if flow_sum > 0 : # 吸液
                move_type = "吸液"
            if flow_sum < 0 : # 冲液
                move_type = "冲液"
            flow_sum = abs(flow_sum)
            flow_all_sum += flow_sum 
            # 平均流量
            flow_average = flow_sum / t
            # 流量画边界线
            line_min = self.plot_flow.plot(
                [x[p_min], x[p_min]], [-10000, 10000], pen=self.pg.mkPen('b', width=1))
            line_max = self.plot_flow.plot(
                [x[p_max], x[p_max]], [-10000, 10000], pen=self.pg.mkPen('b', width=1))
            # 流量显示文字
            text = pg.TextItem("%.0f ms\r\n%.1f ml\r\n%.1f L/min"%(t, flow_sum, flow_average))
            if move_type == "吸液":
                text.setPos(x[p_min], flow[p_max] * 2)
            if move_type == "冲液":
                text.setPos(x[p_min], flow[p_max] * 1)
            self.plot_flow.addItem(text)

            # 压力
            press_max = max([abs(p) for p in press[p_min:p_max]])
            line_min = self.plot_press.plot(
                [x[p_min], x[p_min]], [-10000, 10000], pen=self.pg.mkPen('b', width=1))
            line_max = self.plot_press.plot(
                [x[p_max], x[p_max]], [-10000, 10000], pen=self.pg.mkPen('b', width=1))
            text = pg.TextItem("%.0f ms\r\n%.1fkPa"%(t, press_max))
            if move_type == "吸液":
                text.setPos(x[p_min], press_max * 2)
            if move_type == "冲液":
                text.setPos(x[p_min], -press_max * 1)
            self.plot_press.addItem(text)
        print("总累积流量： %.1f, 平均流量：%.1f 时间间隔： %s" % (flow_all_sum, flow_all_sum/flow_all_t, flow_all_t))
                


class FlowMeasureDialog(QDialog, Ui_Dialog):

    signal_send = pyqtSignal(str)
    measure_flag = False

    # 压力差值变化阈值
    press_err = 1
    # 压力差值变化忽略范围 间隔*10ms
    press_err_miss_interval = 200
    # 变化之后的计数
    press_err_cnt = 0
    # 压力变化标志
    press_change_flag = False
    # 压力变化次数
    press_change_cnt = 0
    # 压力方向
    press_direction = '+'

    # 脉冲基础数据
    flow_base = 0
    # 正向累积流量
    flow_positive_total = 0
    # 反向累积流量
    flow_negative_total = 0

    # 时间基础数据
    time_base = 0

    # 计数
    cnt = 0
    data = []


    def __init__(self, parent=None):
        super(QDialog, self).__init__(parent)
        self.setupUi(self)
        self.setWindowIcon(QIcon(':icons/img/box.png'))
        self.setWindowTitle("流量测量")
        # 曲线
        self.line = LineGraphWidget()
        # self.linex = graphWidget()
        self.verticalLayout_graph.addWidget(self.line)
        # 表格
        self.tableView = TableView()
        self.tableView.setHeader(header=['时间(ms)', '流量(f)', '压力(kPa)'])
        self.tableView.clear_data()
        self.verticalLayout_table.addWidget(self.tableView)

        # 串口模块
        self.pushButton_start.clicked.connect(self.start)
        self.pushButton_stop.clicked.connect(self.stop)
        self.pushButton_getResult.clicked.connect(self.getResult)

        self.timer_test = QTimer()
        self.timer_test.timeout.connect(self.timerTest)
        self.timer_test_cnt = 0

    def start(self):
        '''开始'''
        cmd = ComDeal.getCmd2(WATER_CMD['开始测量'])
        self.signal_send.emit(cmd)
        self.measure_flag = True
        # 清除曲线数据
        self.line.clear_data()
        # 清除表格数据
        self.tableView.clear_data()
        # 清除相关变量
        self.cnt = 0
        self.flow_base = 0
        self.press_direction = "+"
        self.change_flag = False
        self.time_base = 0
        self.data = []

    def stop(self):
        '''停止'''
        self.measure_flag = False
        cmd = ComDeal.getCmd2(WATER_CMD['停止测量'])
        self.signal_send.emit(cmd)

    # @pysnooper.snoop()
    def serialDeal(self, cmd, data):
        if cmd == "71":
            t = MathFunc.HexToInt(data[0:8]) * 10
            flow = MathFunc.HexToInt(data[8:16])
            press = float("%.3f" % MathFunc.HexToFloat(data[16:24]))
            logging.info("接收到数据：时间：%s, 流量：%s, 压力：%s" % (t, flow, press))
            # self.dealDataAll(t, flow, press)
            self.testData(t, flow, press)
    
    def testData(self, t, flow, press):
        """采集测试数据"""
        self.line.draw_two(t, flow, press)
        self.tableView.add_data([t, flow, press])

    def dealDataAll(self, t, flow, press):
        # 开始的方向根据压力判断
        if self.cnt < self.press_err_miss_interval:
            if press > 0:
                self.press_direction = '+'
            if press < 0:
                self.press_direction = '-'
        if self.cnt > 5:
            # pre_data = self.tableView.getDataRows(self.cnt - 5)
            pre_data = self.data[self.cnt - 3]
            pre_time = pre_data[0]
            pre_flow = pre_data[1]
            pre_press = pre_data[2]
            # 差值判断
            if abs(press - pre_press) > self.press_err:
                # print("*"*500)
                if self.press_change_flag == False:
                    self.press_change_flag = True
                    # 记录变化次数
                    self.press_change_cnt += 1
                    if self.press_change_cnt == 1:
                        self.time_base = t
                    # 更新流量基础值
                    self.flow_base = flow
                    # 转变方向
                    if self.press_direction == '+':
                        self.press_direction = "-"
                    else:
                        self.press_direction = "+"
                # print(self.press_change_cnt)
        # 压力变化开始计时变化范围
        if self.press_change_flag:
            self.press_err_cnt += 1
        # 判断是否在压力变化不考虑的范围
        if self.press_err_cnt > self.press_err_miss_interval:
            self.press_err_cnt = 0
            self.press_change_flag = False
        # 流量减去其基础值
        flow = flow - self.flow_base
        # 保存数据
        self.data.append([t, flow, press])
        # 去除开机第一次采集
        if self.press_change_cnt > 0:
            t = t - self.time_base
            if self.press_direction == "-":
                self.line.draw_two(t, -flow, press)
                self.tableView.add_data([t, -flow, press])
            else:
                self.line.draw_two(t, flow, press)
                self.tableView.add_data([t, flow, press])
        # 计数
        self.cnt += 1

    def dealData(self, t, flow, press):
        # 开始的方向根据压力判断
        if self.cnt < self.press_err_miss_interval:
            if press > 0:
                self.press_direction = '+'
            if press < 0:
                self.press_direction = '-'
        if self.cnt > 5:
            # pre_data = self.tableView.getDataRows(self.cnt - 5)
            pre_data = self.data[self.cnt - 3]
            pre_time = pre_data[0]
            pre_flow = pre_data[1]
            pre_press = pre_data[2]
            # 差值判断
            if abs(press - pre_press) > self.press_err:
                # print("*"*500)
                if self.press_change_flag == False:
                    self.press_change_flag = True
                    # 记录变化次数
                    self.press_change_cnt += 1
                    if self.press_change_cnt == 1:
                        self.time_base = t
                    # 更新流量基础值
                    self.flow_base = flow
                    # 转变方向
                    if self.press_direction == '+':
                        self.press_direction = "-"
                    else:
                        self.press_direction = "+"
                # print(self.press_change_cnt)
        # 压力变化开始计时变化范围
        if self.press_change_flag:
            self.press_err_cnt += 1
        # 判断是否在压力变化不考虑的范围
        if self.press_err_cnt > self.press_err_miss_interval:
            self.press_err_cnt = 0
            self.press_change_flag = False
        # 流量减去其基础值
        flow = flow - self.flow_base
        # 保存数据
        self.data.append([t, flow, press])
        # 去除开机第一次采集
        if self.press_change_cnt > 0:
            t = t - self.time_base
            if self.press_direction == "-":
                self.line.draw_two(t, -flow, press)
                self.tableView.add_data([t, -flow, press])
                self.flow_negative_total += flow
            else:
                self.line.draw_two(t, flow, press)
                self.tableView.add_data([t, flow, press])
                self.flow_positive_total += flow
            # self.label.setText("时间：%d ms / 正向累积流量: %.3f / 反向累积流量：%.3f" %
            #                    (t, self.flow_positive_total, self.flow_negative_total))
        # 计数
        self.cnt += 1

    def getResult(self):
        self.line.clear_data()
        self.test_data = Excel.read_data_rows("%s/data/test3.xls" % os.getcwd(), "sheet1")
        self.timer_test.start(1)

    def timerTest(self):
        self.timer_test_cnt += 1
        if self.timer_test_cnt < len(self.test_data):
            data = self.test_data
            i = self.timer_test_cnt
            t = float(data[i][0])
            flow = float(data[i][1])
            press = float(data[i][2])
            self.line.draw_two(t, flow, press)
            # self.tableView.add_data([t, flow, press])
        else:
            self.timer_test.stop()


